﻿/* $RCSFile: CrmUtil4Form.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/CRMWrapper3/CrmUtil4Form.cs $
 * $log$
 * Revision 6 2010/08/06 19:56:31  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Xml;
using System.IO;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Configuration;
using System.Web.Services.Protocols;
using System.Globalization;

using CrmSdk.CRM4;

using AddonNice.CRMWrapper.Design;
using AddonNice.CRMWrapper.CRM4Server;
using AddonNice.CRMWrapper.CRM4Meta;

namespace AddonNice.CRMWrapper
{

    #region Utilities to build internal trees independantly of UI components
    
    public enum NodeType { UnKnown,Entity,FormsCol,Form,DatasCol,Data,EventsCol,
        Event,Script,TabsCol,Tab,SectionsCol,Section,Label,
        RowsCol,Row,Cell,Control,Parameter,Detail,
        SiteMap,Areas,Area,Group,SubAreas,SubArea,Title,Description,Privilege, // SiteMap
    };

    public class NodeUtil
    {
        
        public List<NodeUtil> Nodes     =   new List<NodeUtil>();
        public NodeUtil Sibling         =   null;
        public string Text              =   string.Empty;
        public string Id                =   string.Empty;
        public NodeType Type            =   NodeType.UnKnown;

        public NodeUtil()
        {
        }
        public NodeUtil(NodeType Tp)
        {
            Type    =   Tp;
        }

        public NodeUtil(string nm,NodeType Tp)
        {
            Type    =   Tp;
            Text    =   nm;
        }

        public NodeUtil(string nm,string id,NodeType Tp)
        {
            Type    =   Tp;
            Text    =   nm;
            Id      =   id;
        }
    }

    public class TreeUtil
    {
        public NodeUtil Node   =   null;
        public TreeUtil(string firstNodeText,NodeType tp)
        {
            Node   =   new NodeUtil(firstNodeText,tp);
        }
    }
    
    #endregion Utilities to build internal trees independantly of UI componenets

    /// <summary>
    /// Defines the columns parameter for sections
    /// </summary>
    public enum SectionColumnsLayout {Cols11=0,Cols12,Cols21,Cols3,Cols4};
    
    /// <summary>
    /// Toolkit to modify CRM forms and Views
    /// Add an iFrame in tab/section
    /// Add attributes in tab/section
    /// Import/Export frame datas
    /// </summary>
    public class CrmUtil4Form
    {
        #region clsid for controls in CRM forms

        const string clsIdCheckBox          =   "{B0C6723A-8503-4fd7-BB28-C8A06AC933C2}";
        const string clsIdDateTime          =   "{5B773807-9FB2-42db-97C3-7A91EFF8ADFF}";
        const string clsIdDecimal           =   "{C3EFE0C3-0EC6-42be-8349-CBD9079DFD8E}";
        const string clsIdDuration          =   "{AA987274-CE4E-4271-A803-66164311A958}";
        const string clsIdEmailAddress      =   "{ADA2203E-B4CD-49be-9DDF-234642B43B52}";
        const string clsIdEmailBody         =   "{6F3FB987-393B-4d2d-859F-9D0F0349B6AD}"; 
        const string clsIdFloat             =   "{0D2C745A-E5A8-4c8f-BA63-C6D3BB604660}"; 
        const string clsIdIFrame            =   "{FD2A7985-3187-444e-908D-6624B21F69C0}"; 
        const string clsIdInteger           =   "{C6D124CA-7EDA-4a60-AEA9-7FB8D318B68F}"; 
        const string clsIdLanguage          =   "{671A9387-CA5A-4d1e-8AB7-06E39DDCF6B5}"; 
        const string clsIdLookup            =   "{270BD3DB-D9AF-4782-9025-509E298DEC0A}"; 
        const string clsIdMoney             =   "{533B9E00-756B-4312-95A0-DC888637AC78}"; 
        const string clsIdNotes             =   "{06375649-c143-495e-a496-c962e5b4488e}"; 
        const string clsIdPartyListLookup   =   "{CBFB742C-14E7-4a17-96BB-1A13F7F64AA2}"; 
        const string clsIdPicklist          =   "{3EF39988-22BB-4f0b-BBBE-64B5A3748AEE}"; 
        const string clsIdRadiobuttons      =   "{67FAC785-CD58-4f9f-ABB3-4B7DDC6ED5ED}"; 
        const string clsIdRegardingLookup   =   "{F3015350-44A2-4aa0-97B5-00166532B5E9}"; 
        const string clsIdStatusReason      =   "{5D68B988-0661-4db2-BC3E-17598AD3BE6C}"; 
        const string clsIdTextArea          =   "{E0DECE4B-6FC8-4a8f-A065-082708572369}"; 
        const string clsIdTextBox           =   "{4273EDBD-AC1D-40d3-9FB2-095C621B552D}"; 
        const string clsIdTickerSymbol      =   "{1E1FC551-F7A8-43af-AC34-A8DC35C7B6D4}"; 
        const string clsIdTimeZonePicklist  =   "{7C624A0B-F59E-493d-9583-638D34759266}"; 
        const string clsIdUrl               =   "{71716B6C-711E-476c-8AB8-5D11542BFB47}";

        #endregion clsid for controls in CRM forms
        
        #region exportable entities

        public string[] Entities4Export={    
                "account",
                "activitypointer",
                "appointment",
                "bulkoperation",
                "businessunit",
                "campaign",
                "campaignactivity",
                "campaignresponse",
                "competitor",
                "constraintbasedgroup",
                "contact",
                "contract",
                "contractdetail",
                "contracttemplate",
                "customeraddress",
                "customeropportunityrole",
                "customerrelationship",
                "discount",
                "discounttype",
                "duplicaterule",
                "email",
                "equipment",
                "fax",
                "incident",
                "incidentresolution",
                "invoice",
                "invoicedetail",
                "lead",
                "letter",
                "list",
                "mailmergetemplate",
                "opportunity",
                "opportunityproduct",
                "phonecall",
                "pricelevel",
                "product",
                "productpricelevel",
                "quote",
                "quotedetail",
                "report",
                "reportcategory",
                "role",
                "salesliterature",
                "salesorder",
                "salesorderdetail",
                "serviceappointment",
                "subject",
                "systemuser",
                "task",
                "team",
                "template",
                "territory",
                "transactioncurrency",
                "uom",
                "uomschedule"
                };

        #endregion exportable entities
        
        #region metadata management

        protected string _DataXml       =   string.Empty;
        public string DataXml           
        {
            get { return _DataXml; }
            set { _DataXml = value; }
        }
        
        bool _MetadataLoaded    =   false;
        public bool MetadataLoaded
        {
            get { return _MetadataLoaded; }
        }
        protected XmlDocument _metadata =   new XmlDocument();
        
        public XmlDocument Metadata
        {
            get { return _metadata; }
            set { _metadata = value; }
        }

        #endregion metadata management

        #region properties

        // Used like pointers when inserting new rows
        XmlElement LastRows     =   null;
        XmlElement LastRowNode  =   null;

        CrmWrapper4 _wrapper    =   null;
        CrmWrapper4 wrapper
        {
            get
            {
                return _wrapper;
            }
        }

        string _entityName  =   string.Empty;
        string entityName
        {
            get
            {
                return _entityName;
            }
        }

        string BuildBy
        {
            get
            {
                return string.Format("Build by Addon Nice on {0:u}",DateTime.Now);
            }
        }

        string _LCID    = System.Threading.Thread.CurrentThread.CurrentCulture.LCID.ToString();
        public string LCID
        {
            get
            {
                return _LCID;
            }
        }

        #region output/output values to set before or automatically selected 

        string _entityDisplayName   =   string.Empty;
        public string entityDisplayName
        {
            get
            {
                if ( _entityDisplayName == string.Empty )
                    return _entityName;
                return _entityDisplayName;
            }
            set
            {
                _entityDisplayName  =   value.Trim().Replace(' ','_');
            }
        }

        int _rowSpan         =   7;
        
        /// <summary>
        /// Default value: 7
        /// </summary>
        public int rowSpan
        {
            get
            {
                return _rowSpan;
            }
            set
            {
                _rowSpan  =   value;
            }
        }
        
        int _colSpan         =   2;
        /// <summary>
        /// Default value: 2
        /// </summary>
        public int colSpan
        {
            get
            {
                return _colSpan;
            }
            set
            {
                _colSpan  =   value;
            }
        }

        string _iFrameName   =   string.Empty;
        /// <summary>
        /// Default value: ADDONNICE{0}",entityDisplayName
        /// </summary>
        public string iFrameName
        {
            get
            {
                if ( _iFrameName == string.Empty )
                    _iFrameName =   string.Format("ADDONNICE{0}",entityDisplayName.ToUpper());
                return _iFrameName;
            }
            set
            {
                _iFrameName  =   value;
            }
        }

        
        string _iFrameTabName               =   string.Empty;
        /// <summary>
        /// Default value: Addon Nice {0}",entityDisplayName
        /// </summary>
        public string iFrameTabName
        {
            get
            {
                if ( _iFrameTabName == string.Empty )
                    _iFrameTabName  =   string.Format("Addon Nice {0}",entityDisplayName);
                return _iFrameTabName;
            }
            set
            {
                _iFrameTabName  =   value;
            }
        }

        string _iFrameSectionName           =   string.Empty;
        /// <summary>
        /// Default value: View {0}",entityDisplayName
        /// </summary>
        public string iFrameSectionName           
        {
            get
            {
                if ( _iFrameSectionName == string.Empty )
                    _iFrameSectionName  =   string.Format("View {0}",entityDisplayName);
                return _iFrameSectionName;
            }
            set
            {
                _iFrameSectionName  =   value;
            }
        }


        #endregion output/output values to set before or automatically selected 
        
        #endregion properties

        #region Ctor

        public CrmUtil4Form(CrmWrapper4 wrap,string entName)
        {
            _wrapper        =   wrap;
            _entityName     =   entName;
        }

        #endregion Ctor

        #region Add New Tab / Section

        void LoadMetaData()
        {
            _metadata               =   new XmlDocument();
            if (string.IsNullOrEmpty(DataXml))
            {
                const string msg    =  "[E]CrmUtil4Form LoadMetaData crm metadata not imported.";
                if ( CRMMetaTrace.Sw.TraceError || InstallTraceSwitchW.Sw.TraceError )
                    Trace.WriteLine( msg,(CRMMetaTrace.Sw.TraceError) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw new ArgumentException(msg);
            }
            _metadata.LoadXml(DataXml);
            _MetadataLoaded =   true;
        }

        public XmlNode FormNode
        {
            get
            {
                string path = "//ImportExportXml/Entities/Entity/FormXml/forms/entity/form[@type='main']";
                if ( !MetadataLoaded )
                    LoadMetaData();
                XmlNode _formNode = _metadata.SelectSingleNode(path);
                return _formNode;
            }
        }

        public XmlElement AddNewTab(string TabName)
        {
            XmlNode tabsNode        =   FormNode.SelectSingleNode("tabs");
            XmlElement newTab       =   _metadata.CreateElement("tab");
            tabsNode.AppendChild(newTab);
            /*
              <xs:attribute name="group" type="xs:string" />
              <xs:attribute name="name" type="xs:string" />
              <xs:attribute name="verticallayout" type="xs:boolean" />
              <xs:attribute name="showlabel" type="xs:boolean" />
              <xs:attribute name="id" type="GuidType" />
              <xs:attribute name="IsUserDefined" type="xs:string" />
              <xs:attribute name="locklevel" type="xs:nonNegativeInteger" />
              <xs:attribute name="addedby" type="xs:string" />
            */

            XmlAttribute att        =   _metadata.CreateAttribute("id");
            att.Value               =   "{" + Guid.NewGuid().ToString() + "}";
            newTab.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("name");
            att.Value               =   TabName;
            newTab.Attributes.Append(att);
            
            att                     =   _metadata.CreateAttribute("verticallayout");
            att.Value               =   "true";
            newTab.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("IsUserDefined");
            att.Value               =   "1";
            newTab.Attributes.Append(att);
            
            XmlElement TabLabels    =   _metadata.CreateElement("labels");
            newTab.AppendChild(TabLabels);
            XmlElement TabLab       =   _metadata.CreateElement("label");
            att                     =   _metadata.CreateAttribute("description");
            att.Value               =   TabName;
            TabLab.Attributes.Append(att);
            att                     =   _metadata.CreateAttribute("languagecode");
            att.Value               =   LCID;
            TabLab.Attributes.Append(att);

            TabLabels.AppendChild(TabLab);

            XmlNode sections        =   _metadata.CreateElement("sections");
            newTab.AppendChild(sections);

            return newTab;
        }

        /// <summary>
        /// Add a new section
        /// Default to VarWidth for section layout and Cols11 for columbs layout
        /// </summary>
        public XmlElement AddNewSection(XmlElement newTab,string sectionName)
        {
            return AddNewSection(newTab,sectionName,true);
        }

        /// <summary>
        /// Add a new section
        /// Default Cols11 for columbs layout
        /// </summary>
        public XmlElement AddNewSection(XmlElement newTab,string sectionName, bool LayoutVarWidth)
        {
            return AddNewSection(newTab,sectionName,LayoutVarWidth,SectionColumnsLayout.Cols11,false);
        }
        
        /// <summary>
        /// Add new section with all parameters
        /// colLt is the number of columns layout
        /// LayoutVarWidth when set to false use the varheight value and heigth is set to auto, else height is not specified
        /// forceAutoHeight will force height=auto to extend vertically all fields,default false
        /// </summary>
        public XmlElement AddNewSection(XmlElement newTab,string sectionName, bool LayoutVarWidth,SectionColumnsLayout colLt,bool forceAutoHeight)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddNewSection BEG tabName: {0}, LayoutVarWidth: {1}, colLt: {2}", 
                    iFrameTabName,LayoutVarWidth,colLt),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);

            XmlNode sections        =   newTab.SelectSingleNode("sections");
            if ( sections == null )
            {
                sections            =   _metadata.CreateElement("sections");
                newTab.AppendChild(sections);
            }
            
            XmlElement sectionNode  =   _metadata.CreateElement("section");
            sections.AppendChild(sectionNode);
            /*
              <xs:attribute name="name" type="xs:string" />
              <xs:attribute name="showlabel" type="xs:boolean" />
              <xs:attribute name="showbar" type="xs:boolean" />
              <xs:attribute name="id" type="GuidType" />
              <xs:attribute name="IsUserDefined" type="xs:string" />
              <xs:attribute name="height" type="xs:string" />
              <xs:attribute name="locklevel" type="xs:nonNegativeInteger" />
              <xs:attribute name="labelwidth" type="xs:nonNegativeInteger" />
              <xs:attribute name="layout" type="xs:string" />
              <xs:attribute name="columns" type="xs:nonNegativeInteger" />
              <xs:attribute name="addedby" type="xs:string" />
             */

            XmlAttribute att        =   _metadata.CreateAttribute("id");
            att.Value               =   "{"+Guid.NewGuid().ToString()+"}";
            sectionNode.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("name");
            att.Value               =   sectionName;
            sectionNode.Attributes.Append(att);
            
            att                     =   _metadata.CreateAttribute("IsUserDefined");
            att.Value               =   "1";
            sectionNode.Attributes.Append(att);
            
            // sdk:default-> variable field width (varwidth), else fixed field width (varheight)
            att                     =   _metadata.CreateAttribute("layout");
            if ( LayoutVarWidth )
                    att.Value       =   "varwidth";
            else    att.Value       =   "varheight";
            sectionNode.Attributes.Append(att);
            
            att                     =   _metadata.CreateAttribute("showlabel");
            att.Value               =   "false";
            sectionNode.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("showbar");
            att.Value               =   "false";
            sectionNode.Attributes.Append(att);
            if ( !LayoutVarWidth || forceAutoHeight )
            {
                att                 =   _metadata.CreateAttribute("height");
                att.Value           =   "auto";
                sectionNode.Attributes.Append(att);
            }

            att                     =   _metadata.CreateAttribute("columns");
            switch( colLt)
            {
                default:
                case SectionColumnsLayout.Cols11:
                att.Value               =   "11";
                break;
                case SectionColumnsLayout.Cols12:
                att.Value               =   "12";
                break;
                case SectionColumnsLayout.Cols21:
                att.Value               =   "11";
                break;
                case SectionColumnsLayout.Cols3:
                att.Value               =   "3";
                break;
                case SectionColumnsLayout.Cols4:
                att.Value               =   "4";
                break;
            }
            sectionNode.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("labelwidth");
            att.Value               =   "115";
            sectionNode.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("addedby");
            att.Value               =   BuildBy;
            sectionNode.Attributes.Append(att);

            XmlElement TabLabels    =   _metadata.CreateElement("labels");
            sectionNode.AppendChild(TabLabels);
            XmlElement TabLab       =   _metadata.CreateElement("label");
            att                     =   _metadata.CreateAttribute("description");
            att.Value               =   sectionName;
            TabLab.Attributes.Append(att);
            att                     =   _metadata.CreateAttribute("languagecode");
            att.Value               =   LCID;
            TabLab.Attributes.Append(att);

            TabLabels.AppendChild(TabLab);

            XmlElement rows         =   _metadata.CreateElement("rows");
            /*
            att                     =   _metadata.CreateAttribute("addedby");
            att.Value               =   BuildBy;
            rows.Attributes.Append(att);
            */
            sectionNode.AppendChild(rows);
            return sectionNode;
        }

        #endregion Add New Tab / Section
        
        #region Testing existence

        /// <summary>
        /// Return the internal tab name or string.Empty
        /// </summary>
        public string GetTabId(XmlElement tab)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( "[V]CrmUtil4Form GetTabId BEG.",(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            // "tabs/tab[@id='{0}']",iFrameTabName));
            string tabName  =    string.Empty;
            try
            {
                tabName     =   ( tab.Attributes["id"] != null ) ? tab.Attributes["id"].InnerXml : string.Empty;
            }
            catch ( Exception ex )
            {
                if ( CRMMetaTrace.Sw.TraceError || InstallTraceSwitchW.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CrmUtil4Form GetTabId ex: {0}", ex ),(CRMMetaTrace.Sw.TraceError) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            }
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form GetTabId id: {0}", tabName ),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return tabName;
        }

        /// <summary>
        /// Return the internal tab name or string.Empty
        /// </summary>
        public string GetTabName(XmlElement tab)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( "[V]CrmUtil4Form GetTabName BEG.",(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            // "tabs/tab[@name='{0}']",iFrameTabName));
            string tabName  =    string.Empty;
            try
            {
                tabName     =   ( tab.Attributes["name"] != null ) ? tab.Attributes["name"].InnerXml : string.Empty;
            }
            catch ( Exception ex )
            {
                if ( CRMMetaTrace.Sw.TraceError || InstallTraceSwitchW.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CrmUtil4Form GetTabName ex: {0}", ex ),(CRMMetaTrace.Sw.TraceError) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            }
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form GetTabName tabName: {0}", tabName ),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return tabName;
        }

        /// <summary>
        /// Return the internal tab name or string.Empty
        /// </summary>
        public string GetTabFirstLabel(XmlElement tab)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( "[V]CrmUtil4Form GetTabFirstLabel BEG.",(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            XmlElement labNode         =   (XmlElement)tab.SelectSingleNode("labels/label");
            if ( labNode == null )
                return string.Empty;
            string tabName          =    string.Empty;
            try
            {
                tabName     =   ( labNode.Attributes["description"] != null ) ? labNode.Attributes["description"].InnerXml : string.Empty;
            }
            catch ( Exception ex )
            {
                if ( CRMMetaTrace.Sw.TraceError || InstallTraceSwitchW.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CrmUtil4Form GetTabFirstLabel ex: {0}", ex ),(CRMMetaTrace.Sw.TraceError) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            }
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form GetTabFirstLabel tabName: {0}", tabName ),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return tabName;
        }

        public string GetFirstTabName()
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine("[V]CrmUtil4Form GetFirstTabName BEG.",(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            XmlNodeList Tabs        =   FormNode.SelectNodes("tabs/tab");
            if ( ( Tabs == null ) || ( Tabs.Count == 0 ) )
                return string.Empty;
            XmlElement newTab       =   (XmlElement)Tabs[0];
            return GetTabName(newTab);
        }

        public XmlElement GetFirstTab()
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine("[V]CrmUtil4Form GetFirstTabName BEG.",(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            XmlNodeList Tabs        =   FormNode.SelectNodes("tabs/tab");
            if ( ( Tabs == null ) || ( Tabs.Count == 0 ) )
                return null;
            return  (XmlElement)Tabs[0];
        }

        /// <summary>
        /// Check Tab existing by its name, returns the tab or null
        /// </summary>
        public XmlElement ExistTab(string tabName)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form ExistTab BEG tabName: {0}", tabName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            // try first by name attribute
            XmlElement newTab       =   (XmlElement)FormNode.SelectSingleNode(string.Format("tabs/tab[@name='{0}']",tabName)); 
            if ( newTab != null )
                return newTab;
            // second try on labels
            XmlNode labNode         =   FormNode.SelectSingleNode(string.Format("tabs/tab/labels/label[@description='{0}']",tabName));
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form ExistTab tab labNode found: {0}", (labNode != null) ),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            if ( labNode == null )
                return null;
            XmlElement tb           =   (XmlElement)labNode.SelectSingleNode("..").SelectSingleNode("..");
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form ExistTab tab found: {0}", (tb != null) ),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return tb;
        }
        
        /// <summary>
        /// If exists returns the section
        /// </summary>
        public XmlElement ExistSection(string tabName,string sectionName)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form ExistSection BEG tabName: {0}, sectionName: {1}",tabName,sectionName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            XmlElement Tab         =   ExistTab(tabName);
            if ( Tab == null )
                return null;
            // first try with name
            XmlElement sectionNode  =   (XmlElement)Tab.SelectSingleNode(string.Format("sections/section[@name='{0}']",iFrameSectionName));
            if ( sectionNode != null )
                return sectionNode;
            // second try with label
            XmlNode sections       =   Tab.SelectSingleNode(string.Format("sections/section/labels/label[@description='{0}']",sectionName));
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form ExistSection sections found: {0}", (sections != null) ),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            if ( sections == null )
                return null;
            XmlElement sec          =    (XmlElement)sections.SelectSingleNode("..").SelectSingleNode("..");
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form ExistSection section found: {0}", (sec != null) ),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return sec;
        }

        /// <summary>
        /// If exists, returns the control containing the attribute
        /// </summary>
        public XmlElement ExistAttribute(string tabName,string sectionName,string AttName)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form ,string AttName BEG tabName: {0}, sectionName: {1}",tabName,sectionName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            XmlElement section  =   ExistSection(tabName,sectionName);
            if ( section == null )
                return null;
            XmlNode ctl      =   section.SelectSingleNode(string.Format("rows/row/cell/control[@id='{0}']",AttName));
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form ExistAttribute ctl found: {0}", (ctl != null) ),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return (XmlElement)ctl;
        }
        
        public bool ExistAttributeInFirstTabAndSection(string AttName)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form ExistAttributeInFirstTabAndSection BEG AttName: {0}.",AttName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);

            XmlNodeList Tabs        =   FormNode.SelectNodes("tabs/tab");
            if ( ( Tabs == null ) || ( Tabs.Count == 0 ) )
                return false;
            XmlElement newTab       =   (XmlElement)Tabs[0];
            XmlNodeList Secs        =   newTab.SelectNodes("sections/section");
            if ( ( Secs == null ) || ( Secs.Count == 0 ) )
                return false;
            XmlElement section      =   (XmlElement)Secs[0];
            XmlNode ctl      =   section.SelectSingleNode(string.Format("rows/row/cell/control[@id='{0}']",AttName));
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form ExistAttributeInFirstTabAndSection ctl found: {0}", (ctl != null) ),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return (ctl != null);
        }

        #endregion Testing existence

        #region Add attribute
        /// <summary>
        /// rowspan default to ( aType == AttributeInternalType.Memo ) ? 4:1;
        /// colspan to 2
        /// </summary>
        public bool AddAttributeInExistingTabAndSection(string tabName, string sectionName,string AttName, string displayName, AttributeInternalType aType)
        {
            int rowspan     =   ( aType == AttributeInternalType.Memo ) ? 4:1;
            return AddAttributeInExistingTabAndSection(tabName, sectionName, AttName, displayName, aType, 2, rowspan);
        }

        public bool AddAttributeInExistingTabAndSection(string tabName,string sectionName,string AttName,string displayName,
            AttributeInternalType aType,int colspan,int rowspan )
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddAttributeInExistingTabAndSection BEG tabName: {0}, sectionName: {1}, colspan: {2}, rowspan: {3}", 
                    new object[]{tabName,sectionName,colspan,rowspan}),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);

            XmlNode labNode         =   FormNode.SelectSingleNode(string.Format("tabs/tab/labels/label[@description='{0}']",tabName));
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddAttributeInExistingTabAndSection tab labNode found: {0}", (labNode != null) ),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            XmlElement newTab       =   (XmlElement)labNode.SelectSingleNode("..").SelectSingleNode("..");

            return AddAttributeInExistingSection(newTab,sectionName,AttName.Trim(),displayName,aType,colspan,rowspan);
        }

        public bool AddAttributeInFirstTabAndSection(string AttName,string displayName,AttributeInternalType aType,int colspan,int rowspan )
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddAttributeInFirstTabAndSection BEG AttName: {0}, colspan: {1}, rowspan: {2}", 
                    AttName,colspan,rowspan),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);

            XmlNodeList Tabs        =   FormNode.SelectNodes("tabs/tab");
            if ( ( Tabs == null ) || ( Tabs.Count == 0 ) )
                return false;
            XmlElement newTab       =   (XmlElement)Tabs[0];
            XmlNodeList Secs        =   newTab.SelectNodes("sections/section");
            if ( ( Secs == null ) || ( Secs.Count == 0 ) )
                return false;
            XmlElement sectionNode  =   (XmlElement)Secs[0];
            XmlElement rows         =   (XmlElement)sectionNode.SelectSingleNode("rows");
            if (rows == null)
            {
                rows                =   _metadata.CreateElement("rows");
                sectionNode.AppendChild(rows);
            }
            return AddAttributeInNewRow(rows,AttName.Trim(),displayName,aType,colspan,rowspan);
        }

        public bool AddAttributeInLastRows(string AttName, string displayName, AttributeInternalType aType)
        {
            int rowspan     =   ( aType == AttributeInternalType.Memo ) ? 4:1;
            return AddAttributeInLastRows(AttName, displayName, aType, 2, rowspan);
        }

        public bool AddAttributeInLastRows(string AttName,string displayName,AttributeInternalType aType,int colspan,int rowspan )
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddAttributeInLastRows BEG AttName: {0}, colspan: {1}, rowspan: {2}", 
                    AttName,colspan,rowspan),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);

            if ( LastRows == null)
            {
                string msg = "[E]CrmUtil4Form AddAttributeInLastRows LastRows null.";
                if ( CRMMetaTrace.Sw.TraceError || InstallTraceSwitchW.Sw.TraceError )
                    Trace.WriteLine( msg,(CRMMetaTrace.Sw.TraceError) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw new ArgumentException(msg);
            }
            return AddAttributeInNewRow(LastRows,AttName.Trim(),displayName,aType,colspan,rowspan);
        }

        /// <summary>
        /// rowspan default to ( aType == AttributeInternalType.Memo ) ? 4:1;
        /// colspan to 2
        /// </summary>
        public bool AddAttributeInExistingSection(XmlElement newTab, string sectionName, string AttName, string displayName, AttributeInternalType aType)
        {
            int rowspan     =   ( aType == AttributeInternalType.Memo ) ? 4:1;
            return AddAttributeInExistingSection(newTab, sectionName, AttName, displayName, aType, 2, rowspan);
        }

        public bool AddAttributeInExistingSection(XmlElement newTab,string sectionName,string AttName,string displayName,AttributeInternalType aType,int colspan,int rowspan )
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddAttributeInExistingSection BEG sectionName: {0}",sectionName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            XmlNode sections        =   newTab.SelectSingleNode(string.Format("sections/section/labels/label[@description='{0}']",sectionName));
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddAttributeInExistingSection sections found: {0}", (sections != null) ),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            XmlElement sectionNode  = (XmlElement)sections.SelectSingleNode("..").SelectSingleNode("..");
            XmlElement rows         =   (XmlElement)sectionNode.SelectSingleNode("rows");
            if (rows == null)
            {
                rows                =   _metadata.CreateElement("rows");
                sectionNode.AppendChild(rows);
            }
            return AddAttributeInNewRow(rows,AttName,displayName,aType,colspan,rowspan);
        }
                        

        /// <summary>
        /// rowspan default to ( aType == AttributeInternalType.Memo ) ? 4:1;
        /// colspan to 2
        /// </summary>
        public bool AddAttributeInExistingSection(XmlElement sectionNode,string AttName,string displayName,AttributeInternalType aType)
        {
            int rowspan     =   ( aType == AttributeInternalType.Memo ) ? 4:1;
            return AddAttributeInExistingSection(sectionNode,AttName,displayName,aType,2,rowspan);
        }
        
        public bool AddAttributeInExistingSection(XmlElement sectionNode,string AttName,string displayName,AttributeInternalType aType,int colspan,int rowspan)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine("[V]CrmUtil4Form AddAttributeInExistingSection BEG.",(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            XmlElement rows         =   (XmlElement)sectionNode.SelectSingleNode("rows");
            return AddAttributeInNewRow(rows,AttName,displayName,aType,colspan,rowspan);
        }

        /// <summary>
        /// rowspan default to ( aType == AttributeInternalType.Memo ) ? 4:1;
        /// colspan to 2
        /// </summary>
        bool AddAttributeInNewRow(XmlElement rows, string AttName, string displayName, AttributeInternalType aType)
        {
            int rowspan     =   ( aType == AttributeInternalType.Memo ) ? 4:1;
            return AddAttributeInNewRow(rows, AttName, displayName, aType,2,rowspan);
        }

        /// <summary>
        /// To be synch with a rowspan in a cell, add corresponding rows below the cell row
        /// </summary>
        public void AddEmptyRow(XmlElement rows,int rowspan)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddEmptyRow BEG rowspan: {0}",rowspan),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            XmlElement rowNode          =   null;
            for ( int i=0 ; i < rowspan; i++)
            {
                rowNode                 =   _metadata.CreateElement("row");
                XmlAttribute att        =   _metadata.CreateAttribute("addedby");
                att.Value               =   BuildBy;
                rowNode.Attributes.Append(att);
                rows.AppendChild(rowNode);
            }
            // last row mst have attribute height='auto'
            if (rowNode != null)
            {
                XmlAttribute att        =   _metadata.CreateAttribute("height");
                att.Value               =   "auto";
                rowNode.Attributes.Append(att);
            }
        }

        public bool AddAttributeInSameRow(string AttName,string displayName,AttributeInternalType aType,int colspan,int rowspan)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddAttributeInSameRow BEG rows.HasChildNodes: {0}, AttName: {1}, aType: {2}",
                    LastRows.HasChildNodes,AttName,aType),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            if ( LastRows == null)
            {
                string msg = "[E]CrmUtil4Form AddAttributeInSameRow LastRows null.";
                if ( CRMMetaTrace.Sw.TraceError || InstallTraceSwitchW.Sw.TraceError )
                    Trace.WriteLine( msg,(CRMMetaTrace.Sw.TraceError) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw new ArgumentException(msg);
            }
            if ( LastRowNode == null)
            {
                string msg = "[E]CrmUtil4Form AddAttributeInSameRow LastRowNode null.";
                if ( CRMMetaTrace.Sw.TraceError || InstallTraceSwitchW.Sw.TraceError )
                    Trace.WriteLine( msg,(CRMMetaTrace.Sw.TraceError) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw new ArgumentException(msg);
            }
            return AddAttributeInRow(LastRows,LastRowNode,AttName,displayName,aType,colspan,rowspan);
        }

        public bool AddAttributeInNewRow(XmlElement rows,string AttName,string displayName,AttributeInternalType aType,int colspan,int rowspan)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddAttributeInNewRow BEG rows.HasChildNodes: {0}, AttName: {1}, aType: {2}",
                    rows.HasChildNodes,AttName,aType),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            ///////// ROW //////////////////
            XmlElement rowNode      =   _metadata.CreateElement("row");
/*            
              <xs:attribute name="addedby" type="xs:string" />
              <xs:attribute name="height" type="xs:string" />
 */
            
            XmlAttribute att        =   _metadata.CreateAttribute("addedby");
            att.Value               =   BuildBy;
            rowNode.Attributes.Append(att);
            
            rows.AppendChild(rowNode);
            return AddAttributeInRow(rows,rowNode,AttName,displayName,aType,colspan,rowspan);
        }

        public bool AddAttributeInRow(XmlElement rows,XmlElement rowNode,string AttName,string displayName,AttributeInternalType aType,int colspan,int rowspan)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddAttributeInRow BEG AttName: {0}, aType: {1}",AttName,aType),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);

            LastRows                =   rows;
            LastRowNode             =   rowNode;
            ///////// CELL //////////////////
            XmlElement cellNode     =   _metadata.CreateElement("cell");
/*
            <xs:attribute name="id" type="GuidType" />
            <xs:attribute name="auto" type="xs:boolean" />
            <xs:attribute name="showlabel" type="xs:boolean" />
            <xs:attribute name="locklevel" type="xs:nonNegativeInteger" />
            <xs:attribute name="rowspan" type="xs:nonNegativeInteger" />
            <xs:attribute name="colspan" type="xs:nonNegativeInteger" />
            <xs:attribute name="addedby" type="xs:string" />
*/
            XmlAttribute att        =   _metadata.CreateAttribute("id");
            att.Value               =   "{"+Guid.NewGuid().ToString()+"}";
            cellNode.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("auto");
            att.Value               =   "true";
            cellNode.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("showlabel");
            att.Value               =   "true";
            cellNode.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("colspan");
            att.Value               =   colspan.ToString();
            cellNode.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("rowspan");
            att.Value               =   rowspan.ToString();
            cellNode.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("addedby");
            att.Value               =   BuildBy;
            cellNode.Attributes.Append(att);
            
            rowNode.AppendChild(cellNode);

            XmlElement TabLabels    =   _metadata.CreateElement("labels");
            cellNode.AppendChild(TabLabels);
            XmlElement TabLab       =   _metadata.CreateElement("label");
            att                     =   _metadata.CreateAttribute("description");
            att.Value               =   displayName;
            TabLab.Attributes.Append(att);
            att                     =   _metadata.CreateAttribute("languagecode");
            att.Value               =   LCID;
            TabLab.Attributes.Append(att);

            TabLabels.AppendChild(TabLab);
            
            XmlElement controlNode  =   _metadata.CreateElement("control");
/*
          <xs:attribute name="id" type="xs:string" />
          <xs:attribute name="classid" type="GuidType" />
          <xs:attribute name="datafieldname" type="xs:string" />
          <xs:attribute name="disabled" type="xs:boolean" />
          <xs:attribute name="addedby" type="xs:string" />
 */
            att                     =   _metadata.CreateAttribute("id");
            att.Value               =   AttName;
            controlNode.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("classid");
            switch (aType)
            {
                case AttributeInternalType.Boolean:
                    att.Value           =         clsIdCheckBox;
                    break;
                case AttributeInternalType.DateTime:
                    att.Value           =         clsIdDateTime;
                    break;
                case AttributeInternalType.String:
                    att.Value           =         clsIdTextBox;
                    break;
                case AttributeInternalType.Memo:
                    att.Value           =         clsIdTextArea;
                    break;
                case AttributeInternalType.Money:
                    att.Value           =         clsIdMoney;
                    break;
                case AttributeInternalType.Integer:
                    att.Value           =         clsIdInteger;
                    break;
                case AttributeInternalType.Float:
                    att.Value           =         clsIdFloat;
                    break;
                case AttributeInternalType.Decimal:
                    att.Value           =         clsIdDecimal;
                    break;
                case AttributeInternalType.Picklist:
                    att.Value           =         clsIdPicklist;
                    break;
                case AttributeInternalType.PartyList:
                    att.Value           =         clsIdPartyListLookup;
                    break;
                case AttributeInternalType.Lookup:
                    att.Value           =         clsIdLookup;
                    break;
                case AttributeInternalType.Status:
                    att.Value           =         clsIdStatusReason;
                    break;
                default:
                    {
                        string msg = string.Format("[E]CrmUtil4Form AddAttributeInNewRow AttributeInternalType not supported: {0}",aType);
                        if ( CRMMetaTrace.Sw.TraceError || InstallTraceSwitchW.Sw.TraceError )
                            Trace.WriteLine( msg,(CRMMetaTrace.Sw.TraceError) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                        throw new ArgumentException(msg);
                    }
            }
            controlNode.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("datafieldname");
            att.Value               =   AttName;
            controlNode.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("addedby");
            att.Value               =   BuildBy;
            controlNode.Attributes.Append(att);
            
            cellNode.AppendChild(controlNode);
            if ( rowspan > 1 )
                AddEmptyRow(rows,rowspan-1);            
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddAttributeInNewRow END cellNode: '{0}'",
                    cellNode.InnerText),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return true;
        }

        #endregion Add attribute
        
        #region Add iFrame internal methods

        bool AddIframeInNewTab(string url)
        {
            /////////////////////TABS ///////////////////////////////

            XmlNode tabsNode        =   FormNode.SelectSingleNode("tabs");
            XmlElement newTab       =   _metadata.CreateElement("tab");
            tabsNode.AppendChild(newTab);
            /*
              <xs:attribute name="group" type="xs:string" />
              <xs:attribute name="name" type="xs:string" />
              <xs:attribute name="verticallayout" type="xs:boolean" />
              <xs:attribute name="showlabel" type="xs:boolean" />
              <xs:attribute name="id" type="GuidType" />
              <xs:attribute name="IsUserDefined" type="xs:string" />
              <xs:attribute name="locklevel" type="xs:nonNegativeInteger" />
              <xs:attribute name="addedby" type="xs:string" />
            */

            XmlAttribute att        =   _metadata.CreateAttribute("id");
            att.Value               =   "{" + Guid.NewGuid().ToString() + "}";
            newTab.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("name");
            att.Value               =   iFrameTabName;
            newTab.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("verticallayout");
            att.Value               =   "true";
            newTab.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("IsUserDefined");
            att.Value               =   "1";
            newTab.Attributes.Append(att);
            /*
            att                     =   _metadata.CreateAttribute("addedby");
            att.Value               =   BuildBy;
            newTab.Attributes.Append(att);
            
            
            att                     =   _metadata.CreateAttribute("showlabel");
            att.Value               =   "false";
            newTab.Attributes.Append(att);
            */

            XmlElement TabLabels    =   _metadata.CreateElement("labels");
            newTab.AppendChild(TabLabels);
            XmlElement TabLab       =   _metadata.CreateElement("label");
            att                     =   _metadata.CreateAttribute("description");
            att.Value               =   iFrameTabName;
            TabLab.Attributes.Append(att);
            att                     =   _metadata.CreateAttribute("languagecode");
            att.Value               =   LCID;
            TabLab.Attributes.Append(att);

            TabLabels.AppendChild(TabLab);
            
            XmlNode sections        =   _metadata.CreateElement("sections");
            newTab.AppendChild(sections);

            return AddIframeInNewSection(newTab,url);
        }

            
        bool AddIframeInExistingTabNewSection(string url)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddIframeInExistingTabNewSection BEG tabName: {0}", iFrameTabName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);

            /////////////////////TABS ///////////////////////////////
            /*
            XmlNode labNode         =   FormNode.SelectSingleNode(string.Format("tabs/tab/labels/label[@description='{0}']",iFrameTabName));
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddIframeInExistingTabNewSection labNode found: {0}", (labNode != null) ),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            XmlElement newTab       =   (XmlElement)labNode.SelectSingleNode("..").SelectSingleNode("..");
            */
            //bool useId              =   false;
            XmlElement newTab       =   (XmlElement)FormNode.SelectSingleNode(string.Format("tabs/tab[@name='{0}']",iFrameTabName)); 
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddIframeInExistingTabNewSection newTab found: {0}", (newTab != null) ),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            if ( newTab == null )
            {
                newTab              =   (XmlElement)FormNode.SelectSingleNode(string.Format("tabs/tab[@id='{0}']",iFrameTabName)); 
                //useId               =   true;
                if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddIframeInExistingTabNewSection using id Tab found: {0}", (newTab != null) ),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            }
            if ( newTab == null )
                return false;
            return AddIframeInNewSection(newTab,url);
        }

        bool AddIframeInExistingTabAndSection(string url)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddIframeInExistingTabAndSection BEG tabName: {0}, sectionName: {1}", iFrameTabName,iFrameSectionName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);

            /////////////////////TABS ///////////////////////////////
            /* old search based on label
            XmlNode labNode         =   FormNode.SelectSingleNode(string.Format("tabs/tab/labels/label[@description='{0}']",iFrameTabName));
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddIframeInExistingTabAndSection tab labNode found: {0}", (labNode != null) ),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            XmlElement newTab       =   (XmlElement)labNode.SelectSingleNode("..").SelectSingleNode("..");
            */
            bool useId              =   false;
            XmlElement newTab       =   (XmlElement)FormNode.SelectSingleNode(string.Format("tabs/tab[@name='{0}']",iFrameTabName)); 
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddIframeInExistingTabAndSection newTab found: {0}", (newTab != null) ),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            if ( newTab == null )
            {
                newTab              =   (XmlElement)FormNode.SelectSingleNode(string.Format("tabs/tab[@id='{0}']",iFrameTabName)); 
                useId               =   true;
                if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddIframeInExistingTabAndSection using id Tab found: {0}", (newTab != null) ),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            }
            if ( newTab == null )
                return false;
            return AddIframeInExistingSection(newTab,url,useId);
        }

        public bool AddIframeInExistingXmlSection(XmlElement section,string url)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddIframeInExistingXmlSection BEG tabName: {0}, sectionName: {1}", iFrameTabName,iFrameSectionName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);

            XmlElement rows         =   (XmlElement)section.SelectSingleNode("rows");
            if ( rows == null )
                return false;

            return AddIframeInNewRow(rows,url);
        }

        bool AddIframeInNewSection(XmlElement newTab,string url)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddIframeInNewSection BEG sectionName: {0}",iFrameSectionName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            
            // Add section with variable eight
            XmlElement newSection   =   AddNewSection(newTab,iFrameSectionName, false);
            XmlElement rows         =   (XmlElement)newSection.SelectSingleNode("rows");
            return AddIframeInNewRow(rows,url);
        }
                        
        bool AddIframeInExistingSection(XmlElement newTab,string url,bool useId)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddIframeInExistingSection BEG sectionName: {0}, useid: {1}",iFrameSectionName,useId),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            /* old search based on label
            XmlNode sections        =   newTab.SelectSingleNode(string.Format("sections/section/labels/label[@description='{0}']",iFrameSectionName));
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddIframeInExistingSection sections found: {0}", (sections != null) ),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            XmlElement sectionNode  = (XmlElement)sections.SelectSingleNode("..").SelectSingleNode("..");
             * */
            XmlElement sectionNode  =   null;
            if ( useId )
                sectionNode     =   (XmlElement)newTab.SelectSingleNode(string.Format("sections/section[@id='{0}']",iFrameSectionName));
            else
                sectionNode     =   (XmlElement)newTab.SelectSingleNode(string.Format("sections/section[@name='{0}']",iFrameSectionName));
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddIframeInExistingSection found : {0}",( sectionNode != null )),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            if ( sectionNode == null )
            {
                if ( !useId )
                    sectionNode =   (XmlElement)newTab.SelectSingleNode(string.Format("sections/section[@id='{0}']",iFrameSectionName));
                else
                    sectionNode =   (XmlElement)newTab.SelectSingleNode(string.Format("sections/section[@name='{0}']",iFrameSectionName));
               if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddIframeInExistingSection after inversion found : {0}",( sectionNode != null )),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            }
            if ( sectionNode == null )
                return false;
            XmlElement rows     =   (XmlElement)sectionNode.SelectSingleNode("rows");
            return AddIframeInNewRow(rows,url);
            }
                        

        bool AddIframeInNewRow(XmlElement rows,string url)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddIframeInNewRow BEG rows.HasChildNodes: {0}, colSpan: {1}, rowSpan: {2}",
                    rows.HasChildNodes,colSpan,rowSpan),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            ///////// ROW //////////////////
            XmlElement rowNode      =   _metadata.CreateElement("row");
/*            
              <xs:attribute name="addedby" type="xs:string" />
              <xs:attribute name="height" type="xs:string" />
 */
            
            XmlAttribute att        =   _metadata.CreateAttribute("addedby");
            att.Value               =   BuildBy;
            rowNode.Attributes.Append(att);
            
            rows.AppendChild(rowNode);

            ///////// CELL //////////////////
            XmlElement cellNode     =   _metadata.CreateElement("cell");
/*
            <xs:attribute name="id" type="GuidType" />
            <xs:attribute name="auto" type="xs:boolean" />
            <xs:attribute name="showlabel" type="xs:boolean" />
            <xs:attribute name="locklevel" type="xs:nonNegativeInteger" />
            <xs:attribute name="rowspan" type="xs:nonNegativeInteger" />
            <xs:attribute name="colspan" type="xs:nonNegativeInteger" />
            <xs:attribute name="addedby" type="xs:string" />
*/
            att                     =   _metadata.CreateAttribute("id");
            att.Value               =   "{"+Guid.NewGuid().ToString()+"}";
            cellNode.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("auto");
            att.Value               =   "true";
            cellNode.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("showlabel");
            att.Value               =   "false";
            cellNode.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("rowspan");
            att.Value               =   rowSpan.ToString();
            cellNode.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("colspan");
            att.Value               =   colSpan.ToString();
            cellNode.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("addedby");
            att.Value               =   BuildBy;
            cellNode.Attributes.Append(att);
            
            rowNode.AppendChild(cellNode);

            XmlElement TabLabels    =   _metadata.CreateElement("labels");
            cellNode.AppendChild(TabLabels);
            XmlElement TabLab       =   _metadata.CreateElement("label");
            att                     =   _metadata.CreateAttribute("description");
            att.Value               =   iFrameName;
            TabLab.Attributes.Append(att);
            att                     =   _metadata.CreateAttribute("languagecode");
            att.Value               =   LCID;
            TabLab.Attributes.Append(att);

            TabLabels.AppendChild(TabLab);
            
            XmlElement controlNode  =   _metadata.CreateElement("control");
/*
          <xs:attribute name="id" type="xs:string" />
          <xs:attribute name="classid" type="GuidType" />
          <xs:attribute name="datafieldname" type="xs:string" />
          <xs:attribute name="disabled" type="xs:boolean" />
          <xs:attribute name="addedby" type="xs:string" />
 */
            att                     =   _metadata.CreateAttribute("id");
            att.Value               =   "IFRAME_"+iFrameName.Trim().Replace(' ','_');
            controlNode.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("classid");
            att.Value               =   clsIdIFrame;
            controlNode.Attributes.Append(att);

            att                     =   _metadata.CreateAttribute("addedby");
            att.Value               =   BuildBy;
            controlNode.Attributes.Append(att);
            
            cellNode.AppendChild(controlNode);

            ///////// PARAMETERS //////////////////
            XmlElement parameters   =   _metadata.CreateElement("parameters");
            controlNode.AppendChild(parameters);

            XmlElement urlNode      =   _metadata.CreateElement("Url");
            urlNode.InnerText       =   url;
            parameters.AppendChild(urlNode);

            XmlElement PassParameters      =   _metadata.CreateElement("PassParameters");
            PassParameters.InnerText       =   "true";
            parameters.AppendChild(PassParameters);

            XmlElement Security     =   _metadata.CreateElement("Security");
            Security.InnerText      =   "false";
            parameters.AppendChild(Security);
            
            XmlElement Scrolling    =   _metadata.CreateElement("Scrolling");
            Scrolling.InnerText     =   "auto";
            parameters.AppendChild(Scrolling);
            
            XmlElement Border       =   _metadata.CreateElement("Border");
            Border.InnerText        =   "false";
            parameters.AppendChild(Border);
            
            /*
                  <xs:element name="ViewId" type="GuidType" minOccurs="0" maxOccurs="1" />
                  <xs:element name="Url" type="xs:string" minOccurs="0" maxOccurs="1" />
                  <xs:element name="PassParameters" type="xs:boolean" minOccurs="0" maxOccurs="1" />
                  <xs:element name="Security" type="xs:boolean" minOccurs="0" maxOccurs="1" />
                  <xs:element name="Scrolling" type="xs:string" minOccurs="0" maxOccurs="1" />
                  <xs:element name="Border" type="xs:string" minOccurs="0" maxOccurs="1" />
                  <xs:element name="Preload" type="xs:string" minOccurs="0" maxOccurs="1" />
                  <xs:element name="AutoResolve" type="xs:boolean" minOccurs="0" maxOccurs="1" />
                  <xs:element name="ResolveEmailAddress" type="xs:boolean" minOccurs="0" maxOccurs="1" />
             */
            if ( rowSpan > 1 )
                AddEmptyRow(rows,rowSpan-1);
            return true;
        }

        /*
        <event name="onload" application="0">
        <script><![CDATA[ ]]></script>
        </event>
         */
        /// <summary>
        /// Add a script to Form name is onload or onsave
        /// script is a crm javascript method, just the internal part without braces
        /// </summary>
        public bool AddFormScript(string name,string script)
        {
            XmlNode fNode           =   FormNode;
            XmlNodeList events      =   fNode.SelectNodes("events/event");
            XmlNode searchedNode    =   null;
            foreach (XmlNode eventNode in events)
            {
                if ( name == eventNode.Attributes["name"].InnerText )
                {
                    searchedNode    =   eventNode;
                    break;
                }
            }
            if ( searchedNode == null )
            {
                XmlNode eventsNd    =   fNode.SelectSingleNode("events");
                if ( eventsNd == null )
                {
                    eventsNd        =   _metadata.CreateElement("events");
                    fNode.AppendChild(eventsNd);
                }
                searchedNode        =   _metadata.CreateElement("event");
                eventsNd.AppendChild(searchedNode);
                XmlAttribute att    =   _metadata.CreateAttribute("name");
                att.Value           =   name;
                searchedNode.Attributes.Append(att);
                att                 =   _metadata.CreateAttribute("application");
                att.Value           =   "true";
                searchedNode.Attributes.Append(att);
                att                 =   _metadata.CreateAttribute("active");
                att.Value           =   "true";
                searchedNode.Attributes.Append(att);
                
            }
            XmlNode scriptNode      =   searchedNode.SelectSingleNode("script");
            if (scriptNode == null)
            {
                scriptNode          =   _metadata.CreateElement("script");
                searchedNode.AppendChild(scriptNode);
            }
            scriptNode.InnerText    =   string.Format("![CDATA[{0}]]",script);
            return true;
        }

        #endregion Add iFrame internal methods

        #region Build a tree with Crm frame data

        public TreeUtil BuildDetailledTree(bool fullXml)
        {
            Metadata                =   new XmlDocument();
            _metadata.LoadXml(DataXml);
            
            string path             =   (fullXml) ? "//ImportExportXml/Entities/Entity/FormXml/forms/entity/form" : "//forms/entity/form";
            XmlNodeList Forms       = _metadata.SelectNodes(path);
           
            string entityName       = _metadata.SelectSingleNode((fullXml) ? "//ImportExportXml/Entities/Entity/FormXml/forms/entity":"//forms/entity").Attributes["name"].Value;
            XmlNodeList labels      =   null;
            TreeUtil RadTreeView1   =    new TreeUtil(entityName,NodeType.Entity);
            NodeUtil nd0            =   RadTreeView1.Node;
            NodeUtil  formNd        =   new NodeUtil("Forms",NodeType.FormsCol);
            nd0.Nodes.Add(formNd);
            
            NodeUtil  nd            =   null;
            foreach (XmlNode formNode in Forms)
            {
                StringBuilder sb    =   new StringBuilder();
                sb.AppendFormat("id='{0}', type='{1}'",formNode.Attributes["id"].InnerText,formNode.Attributes["type"].InnerText);
                NodeUtil fnd        =   new NodeUtil(NodeType.Form);
                formNd.Nodes.Add(fnd);
                //Identifies the name of the ISV or customizer that added the element. String Optional 
                if ( formNode.Attributes["addedby"] != null )
                    sb.AppendFormat(", addedby: {0}",formNode.Attributes["addedby"].InnerText);
                //Controls whether the Form Assistant is enabled. The default value is false. Boolean Optional 
                if ( formNode.Attributes["enablerelatedinformation"] != null )
                    sb.AppendFormat(", enablerelatedinformation: {0}",formNode.Attributes["enablerelatedinformation"].InnerText);
                // Internal use only. Boolean Optional 
                if ( formNode.Attributes["hasmargin"] != null )
                    sb.AppendFormat(", hasmargin: {0}",formNode.Attributes["hasmargin"].InnerText);
                // Controls whether the Form Assistant pane is expanded by default. The default value is false. 
                if ( formNode.Attributes["relatedInformationCollapsed"] != null )
                    sb.AppendFormat(", relatedInformationCollapsed: {0}",formNode.Attributes["relatedInformationCollapsed"].InnerText);
                fnd.Text            =   sb.ToString();

                NodeUtil dataNd     =   new NodeUtil("Datas",NodeType.DatasCol);
                fnd.Nodes.Add(dataNd);
                XmlNodeList datas    =   formNode.SelectNodes("data");
                foreach (XmlNode dataNode in datas)
                {
                    //The data element always uses this classid {5546E6CD-394C-4bee-94A8-4425E17EF6C6}
                    // datafieldname matches the control to the name of the data field. String Required 
                    // id Represents the unique identifier used to represent the control in the form
                    nd  =   new NodeUtil(string.Format("{0} - datafield: {1}",dataNode.Attributes["id"].InnerText,dataNode.Attributes["datafieldname"].InnerText),NodeType.Data);
                    dataNd.Nodes.Add(nd);
                }
                NodeUtil eventNd      =   new NodeUtil("Events",NodeType.EventsCol);
                fnd.Nodes.Add(eventNd);
                XmlNodeList events    =   formNode.SelectNodes("events/event");
                if ( events.Count > 0 )
                    fnd.Nodes.Add(eventNd);
                foreach (XmlNode eventNode in events)
                {
                    /*
                    active Describes whether the event is enabled for the form or the field. The default value is false. Boolean Optional 
                                application Internal use only. Boolean Required 
                    BehaviorInBulkEditForm Not used. All scripts are disabled for bulk edit forms String Optional 
                    name Required*/

                    nd  =   new NodeUtil(eventNode.Attributes["name"].InnerText,NodeType.Event);
                    eventNd.Nodes.Add(nd);
                    XmlNodeList scripts    =   eventNode.SelectNodes("script");
                    foreach (XmlNode scriptNode in scripts)
                    {
                        NodeUtil scnd       =   new NodeUtil(scriptNode.InnerText,NodeType.Script);
                        nd.Nodes.Add(scnd);
                    }
                }
                NodeUtil tabsNd             =   new NodeUtil("Tabs",NodeType.TabsCol);
                fnd.Nodes.Add(tabsNd);
                XmlNodeList tabs            =   formNode.SelectNodes("tabs/tab");
                foreach (XmlNode tabNode in tabs)
                {
                    NodeUtil tnd     =   new NodeUtil(NodeType.Tab);
                    sb               =    new StringBuilder();
                    if ( tabNode.Attributes["name"] != null )
                         sb.AppendFormat("{0} id={1} IsUserDefined='{2}' ", tabNode.Attributes["name"].InnerText, tabNode.Attributes["id"].InnerText, tabNode.Attributes["IsUserDefined"].InnerText);
                    else sb.AppendFormat("{0} IsUserDefined='{1}' ", tabNode.Attributes["id"].InnerText, tabNode.Attributes["IsUserDefined"].InnerText);
                    if ( tabNode.Attributes["addedby"] != null )
                        sb.AppendFormat(", addedby: {0}",tabNode.Attributes["addedby"].InnerText);
                    // Not used. String Optional 
                    if ( tabNode.Attributes["group"] != null )
                        sb.AppendFormat(", group: {0}",tabNode.Attributes["group"].InnerText);
                    // Prevents the tab from being deleted from the form or having its properties modified. 0 = Do not lock 
                    if ( tabNode.Attributes["locklevel"] != null )
                        sb.AppendFormat(", locklevel: {0}",tabNode.Attributes["locklevel"].InnerText);
                    // Controls whether the Form Assistant pane is expanded by default. The default value is false. 
                    if ( tabNode.Attributes["showlabel"] != null )
                        sb.AppendFormat(", showlabel: {0}",tabNode.Attributes["showlabel"].InnerText);
                    if ( tabNode.Attributes["verticallayout"] != null )
                        sb.AppendFormat(", verticallayout: {0}",tabNode.Attributes["verticallayout"].InnerText);
                    tnd.Text            =   sb.ToString();
                    tabsNd.Nodes.Add(tnd);
                    labels              =   tabNode.SelectNodes("labels/label");
                    foreach (XmlNode labNode in labels)
                    {
                        nd  =   new NodeUtil(string.Format("languagecode: {0}, Description='{1}'", labNode.Attributes["languagecode"].InnerText,labNode.Attributes["description"].InnerText),NodeType.Label);
                        tnd.Nodes.Add(nd);
                    }
                    NodeUtil sectionsNd     =   new NodeUtil("Sections",NodeType.SectionsCol);
                    tnd.Nodes.Add(sectionsNd);
                    XmlNodeList sections    =   tabNode.SelectNodes("sections/section");
                    foreach (XmlNode sectionNode in sections)
                    {
                        NodeUtil secNd      =   new NodeUtil(NodeType.Section);
                        if ( sectionNode.Attributes["name"] != null )
                                secNd.Text  =   sectionNode.Attributes["name"].InnerText;
                        else    secNd.Text  =   sectionNode.Attributes["id"].InnerText;
                        sectionsNd.Nodes.Add(secNd);
                        StringBuilder sb1   =   new StringBuilder();
                        // The name of the section displayed in the Section properties string Optional  
                        if ( sectionNode.Attributes["name"] != null )
                            sb1.AppendFormat("id='{0}' ", sectionNode.Attributes["id"].InnerText);
                        sb1.AppendFormat("IsUserDefined='{0}'", sectionNode.Attributes["IsUserDefined"].InnerText);
                        //Identifies the name of the ISV or customizer that added the element. string Optional 
                        if ( sectionNode.Attributes["addedby"] != null )
                            sb1.AppendFormat(", addedby: {0}",sectionNode.Attributes["addedby"].InnerText);
                        //Internal use only. Positive Integer Optional 
                        // Controls the height of the section. Set the value to 'auto' to make the section expand to fill all the available space. string Optional 
                        if ( sectionNode.Attributes["height"] != null )
                            sb1.AppendFormat(", height: {0}",sectionNode.Attributes["height"].InnerText);
                        //Defines the horizontal space for a section label in pixels. The default is 110 pixels. Positive Integer Optional 
                        if ( sectionNode.Attributes["labelwidth"] != null )
                            sb1.AppendFormat(", labelwidth: {0}",sectionNode.Attributes["labelwidth"].InnerText);
                        // Defines the section Layout property. Either Variable Field Width (varwidth) or Fixed Field Width (varheight). The default is 'varwidth'. string Optional  
                        if ( sectionNode.Attributes["layout"] != null )
                            sb1.AppendFormat(", layout: {0}",sectionNode.Attributes["layout"].InnerText);
                        // Prevents the section from being deleted from the form or having its properties modified. 
                        if ( sectionNode.Attributes["locklevel"] != null )
                            sb1.AppendFormat(", locklevel: {0}",sectionNode.Attributes["locklevel"].InnerText);
                        //The divider line will only display when the showlabel attribute value is also true.
                        if ( sectionNode.Attributes["showbar"] != null )
                            sb1.AppendFormat(", showbar: {0}",sectionNode.Attributes["showbar"].InnerText);
                        // Show the name of this section on the form 
                        if ( sectionNode.Attributes["showlabel"] != null )
                            sb1.AppendFormat(", showlabel: {0}",sectionNode.Attributes["showlabel"].InnerText);
                        secNd.Nodes.Add(new NodeUtil(sb1.ToString(),NodeType.Detail));
                        
                        labels = sectionNode.SelectNodes("labels/label");
                        foreach (XmlNode labNode in labels)
                        {
                            nd  =   new NodeUtil(string.Format("languagecode: {0}, Description='{1}'", labNode.Attributes["languagecode"].InnerText,labNode.Attributes["description"].InnerText),NodeType.Label);
                            secNd.Nodes.Add(nd);
                        }
                        
                        NodeUtil rowsNd  =   new NodeUtil("Rows",NodeType.RowsCol);
                        secNd.Nodes.Add(rowsNd);
                        XmlNodeList rows = sectionNode.SelectNodes("rows/row");
                        int i   =   1;
                        foreach (XmlNode rowNode in rows)
                        {
                            NodeUtil rNd        =   new NodeUtil(NodeType.Row);
                            if ( rowNode.Attributes["height"] != null )
                                    rNd.Text    =   string.Format("{0}-{1}",i++,rowNode.Attributes["height"].InnerText);
                            else    rNd.Text    =   string.Format("{0}",i++);
                            rowsNd.Nodes.Add(rNd);
                            XmlNodeList cells =  rowNode.SelectNodes("cell");
                            foreach (XmlNode cellNode in cells)
                            {
                                NodeUtil cNd    =   new NodeUtil(NodeType.Cell);
                                if ( cellNode.Attributes["id"] != null )
                                        cNd.Text    =   string.Format("Cell id={0}",cellNode.Attributes["id"].InnerText);
                                else    cNd.Text    =   "Cell";
                                rNd.Nodes.Add(cNd);
                                labels              =   cellNode.SelectNodes("labels/label");
                                foreach (XmlNode labNode in labels)
                                {
                                    nd  =   new NodeUtil(string.Format("languagecode: {0}, Description='{1}'", labNode.Attributes["languagecode"].InnerText,labNode.Attributes["description"].InnerText),NodeType.Label);
                                    cNd.Nodes.Add(nd);
                                }
                                XmlNodeList controls = cellNode.SelectNodes("control");
                                foreach (XmlNode controlNode in controls)
                                {
                                    string clsid = controlNode.Attributes["classid"].InnerText;
                                    StringBuilder sb2   =   new StringBuilder();
                                    sb2.AppendFormat("{0} ", controlNode.Attributes["id"].InnerText);
                                    if ( controlNode.Attributes["datafieldname"] != null )
                                        sb2.AppendFormat("DataFieldName: {0} ", controlNode.Attributes["datafieldname"].InnerText);
                                    if ( controlNode.Attributes["disabled"] != null )
                                        sb1.AppendFormat(", disabled: {0} ",controlNode.Attributes["disabled"].InnerText);
                                    switch (clsid)
                                    {
                                        case clsIdCheckBox:
                                            sb2.Append("CheckBox");
                                            break;
                                        case clsIdDateTime:
                                            sb2.Append("DateTime");
                                            break;
                                        case clsIdDecimal:
                                            sb2.Append("Decimal");
                                            break;
                                        case clsIdDuration:
                                            sb2.Append("Duration");
                                            break;
                                        case clsIdEmailAddress:
                                            sb2.Append("EmailAddress");
                                            break;
                                        case clsIdEmailBody:
                                            sb2.Append("EmailBody");
                                            break;
                                        case clsIdFloat:
                                            sb2.Append("Float");
                                            break;
                                        case clsIdIFrame:
                                            sb2.Append("IFrame");
                                            break;
                                        case clsIdInteger:
                                            sb2.Append("Integer");
                                            break;
                                        case clsIdLanguage:
                                            sb2.Append("Language");
                                            break;
                                        case clsIdLookup:
                                            sb2.Append("Lookup");
                                            break;
                                        case clsIdMoney:
                                            sb2.Append("Money");
                                            break;
                                        case clsIdNotes:
                                            sb2.Append("Notes");
                                            break;
                                        case clsIdPartyListLookup:
                                            sb2.Append("PartyListLookup");
                                            break;
                                        case clsIdPicklist:
                                            sb2.Append("Picklist");
                                            break;
                                        case clsIdRadiobuttons:
                                            sb2.Append("Radiobuttons");
                                            break;
                                        case clsIdRegardingLookup:
                                            sb2.Append("RegardingLookup");
                                            break;
                                        case clsIdStatusReason:
                                            sb2.Append("StatusReason");
                                            break;
                                        case clsIdTextArea:
                                            sb2.Append("TextArea");
                                            break;
                                        case clsIdTextBox:
                                            sb2.Append("TextBox");
                                            break;
                                        case clsIdTickerSymbol:
                                            sb2.Append("TickerSymbol");
                                            break;
                                        case clsIdTimeZonePicklist:
                                            sb2.Append("TimeZonePicklist");
                                            break;
                                        case clsIdUrl:
                                            sb2.Append("Url");
                                            break;
                                        default:
                                            sb2.Append("UNKNOWN");
                                            break;
                                    }
                                    nd  =   new NodeUtil(sb2.ToString(),NodeType.Control);
                                    cNd.Nodes.Add(nd);
                                    XmlNodeList parameters = controlNode.SelectNodes("parameters");
                                    foreach (XmlNode paramNode in parameters)
                                    {
                                        XmlNode snd = paramNode.SelectSingleNode("Url");
                                        if (snd != null)
                                            nd.Nodes.Add(new NodeUtil(string.Format("Url={0}",snd.InnerText),NodeType.Parameter));
                                        snd = paramNode.SelectSingleNode("PassParameters");
                                        if (snd != null)
                                            nd.Nodes.Add(new NodeUtil(string.Format("PassParameters={0}",snd.InnerText),NodeType.Parameter));
                                        snd = paramNode.SelectSingleNode("Security");
                                        if (snd != null)
                                            nd.Nodes.Add(new NodeUtil(string.Format("security={0}",snd.InnerText),NodeType.Parameter));
                                        snd = paramNode.SelectSingleNode("Scrolling");
                                        if (snd != null)
                                            nd.Nodes.Add(new NodeUtil(string.Format("Scrolling={0}",snd.InnerText),NodeType.Parameter));
                                        snd = paramNode.SelectSingleNode("Border");
                                        if (snd != null)
                                            nd.Nodes.Add(new NodeUtil(string.Format("Border={0}",snd.InnerText),NodeType.Parameter));
                                        snd = paramNode.SelectSingleNode("AutoResolve");
                                        if (snd != null)
                                            nd.Nodes.Add(new NodeUtil(string.Format("AutoResolve={0}",snd.InnerText),NodeType.Parameter));
                                    }
                                }
                                events    =   cellNode.SelectNodes("events/event");
                                eventNd  =   new NodeUtil("Events",NodeType.EventsCol);
                                if ( events.Count > 0 )
                                    cNd.Nodes.Add(eventNd);
                                foreach (XmlNode eventNode in events)
                                {
                                    /*
                                    active Describes whether the event is enabled for the form or the field. The default value is false. Boolean Optional 
                                                application Internal use only. Boolean Required 
                                    BehaviorInBulkEditForm Not used. All scripts are disabled for bulk edit forms String Optional 
                                    name Required*/

                                    nd  =   new NodeUtil(eventNode.Attributes["name"].InnerText,NodeType.Event);
                                    eventNd.Nodes.Add(nd);
                                    XmlNodeList scripts    =   eventNode.SelectNodes("script");
                                    foreach (XmlNode scriptNode in scripts)
                                    {
                                        NodeUtil scnd  =   new NodeUtil(scriptNode.InnerXml,NodeType.Script);
                                        nd.Nodes.Add(scnd);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return RadTreeView1;
        }

        /// <summary>
        /// Build a 'user-friendly' tree 
        /// Suppress any grouping intermediate node like tabs-sections-rows-cell
        /// Don't display id but try to set name from lable if existing
        /// Only take main frame if specified
        /// // take current thread language code
        /// </summary>
        public TreeUtil BuildTree(bool fullXml,bool onlyMain)
        {
            Metadata                =   new XmlDocument();
            _metadata.LoadXml(DataXml);
            
            string path             =   (fullXml) ? "//ImportExportXml/Entities/Entity/FormXml/forms/entity/form" : "//forms/entity/form";
            if ( onlyMain )
                path = (fullXml) ? "//ImportExportXml/Entities/Entity/FormXml/forms/entity/form[@type='main']": "//forms/entity/form[@type='main']";

            XmlNodeList Forms       = _metadata.SelectNodes(path);
           
            string entityName       = _metadata.SelectSingleNode((fullXml) ? "//ImportExportXml/Entities/Entity/FormXml/forms/entity":"//forms/entity").Attributes["name"].Value;
            XmlNodeList labels      =   null;
            TreeUtil RadTreeView1   =    new TreeUtil(entityName,NodeType.Entity);
            NodeUtil formNd         =   RadTreeView1.Node;
            
            NodeUtil  nd            =   null;
            foreach (XmlNode formNode in Forms)
            {
                StringBuilder sb    =   new StringBuilder();
                sb.AppendFormat("Form type='{1}'",formNode.Attributes["id"].InnerText,formNode.Attributes["type"].InnerText);
                NodeUtil fnd        =   new NodeUtil(formNode.Attributes["type"].InnerText,formNode.Attributes["id"].InnerText,NodeType.Form);
                formNd.Nodes.Add(fnd);
                //Identifies the name of the ISV or customizer that added the element. String Optional 
                if ( formNode.Attributes["addedby"] != null )
                    sb.AppendFormat(", addedby: {0}",formNode.Attributes["addedby"].InnerText);
                //Controls whether the Form Assistant is enabled. The default value is false. Boolean Optional 
                if ( formNode.Attributes["enablerelatedinformation"] != null )
                    sb.AppendFormat(", enablerelatedinformation: {0}",formNode.Attributes["enablerelatedinformation"].InnerText);
                // Internal use only. Boolean Optional 
                if ( formNode.Attributes["hasmargin"] != null )
                    sb.AppendFormat(", hasmargin: {0}",formNode.Attributes["hasmargin"].InnerText);
                // Controls whether the Form Assistant pane is expanded by default. The default value is false. 
                if ( formNode.Attributes["relatedInformationCollapsed"] != null )
                    sb.AppendFormat(", relatedInformationCollapsed: {0}",formNode.Attributes["relatedInformationCollapsed"].InnerText);
                fnd.Text            =   sb.ToString();

                XmlNodeList tabs            =   formNode.SelectNodes("tabs/tab");
                int tabIdx                  =   0;
                foreach (XmlNode tabNode in tabs)
                {
                    NodeUtil tnd        =   new NodeUtil(NodeType.Tab);
                    tnd.Id              =   tabNode.Attributes["id"].InnerText;
                    sb                  =   new StringBuilder();
                    labels              =   tabNode.SelectNodes("labels/label");
                    bool found          =   false;
                    foreach (XmlNode labNode in labels)
                    {
                        if ((labels.Count == 1) || (labNode.Attributes["languagecode"].InnerText == LCID))
                        {
                            sb.AppendFormat("{0} '{1}'", "Tab", labNode.Attributes["description"].InnerText);
                            found   =   true;
                            break;
                        }
                    }
                    if ( !found )
                       sb.AppendFormat("{0} '{1}'", "Tab",tabIdx );
                    tnd.Text            =   sb.ToString();
                    fnd.Nodes.Add(tnd);
                    tabIdx++;
                    /*
                    NodeUtil nnd     =   new NodeUtil(NodeType.Detail);
                    if ( tabNode.Attributes["IsUserDefined"].InnerText == "true" )
                        sb.Append(" user defined" );
                    if ( tabNode.Attributes["addedby"] != null )
                        sb.AppendFormat(", addedby: {0}",tabNode.Attributes["addedby"].InnerText);
                    // Prevents the tab from being deleted from the form or having its properties modified. 0 = Do not lock 
                    if ( tabNode.Attributes["locklevel"] != null )
                        sb.AppendFormat(", locklevel: {0}",tabNode.Attributes["locklevel"].InnerText);
                    nnd.Text            =   sb.ToString();
                    tnd.Nodes.Add(nnd);
                    */
                    XmlNodeList sections    =   tabNode.SelectNodes("sections/section");
                    int secIdx              =   0;
                    foreach (XmlNode sectionNode in sections)
                    {
                        NodeUtil secNd      =   new NodeUtil(NodeType.Section);
                        secNd.Id            =   sectionNode.Attributes["id"].InnerText;
                        tnd.Nodes.Add(secNd);
                        StringBuilder sb1   =   new StringBuilder();
                        labels              =   sectionNode.SelectNodes("labels/label");
                        found               =   false;
                        foreach (XmlNode labNode in labels)
                        {
                            if ((labels.Count == 1) || (labNode.Attributes["languagecode"].InnerText == LCID))
                            {
                                sb1.AppendFormat("{0} '{1}'", "Section", labNode.Attributes["description"].InnerText);
                                found   =   true;
                                break;
                            }
                        }
                        if ( !found )
                           sb1.AppendFormat("{0} '{1}'", "Section",secIdx );
                        secIdx++;
                        secNd.Text          =   sb1.ToString();
                        /*
                        nnd                 =   new NodeUtil(NodeType.Detail);
                        if ( sectionNode.Attributes["IsUserDefined"].InnerText == "true" )
                            sb1.Append(" user defined" );
                        if ( sectionNode.Attributes["addedby"] != null )
                            sb1.AppendFormat(", addedby: {0}",sectionNode.Attributes["addedby"].InnerText);
                        // Show the name of this section on the form 
                        if ( sectionNode.Attributes["showlabel"] != null )
                            sb1.AppendFormat(", showlabel: {0}",sectionNode.Attributes["showlabel"].InnerText);
                        nnd.Text      =   sb1.ToString();
                        secNd.Nodes.Add(nnd);
                        */
                        XmlNodeList rows = sectionNode.SelectNodes("rows/row");
                        int i   =   1;
                        foreach (XmlNode rowNode in rows)
                        {
                            NodeUtil rNd        =   new NodeUtil(NodeType.Row);
                            rNd.Text            =   string.Format("{0}-{1}","Row",i++);
                            secNd.Nodes.Add(rNd);
                            XmlNodeList cells =  rowNode.SelectNodes("cell");
                            foreach (XmlNode cellNode in cells)
                            {
                                /*
                                NodeUtil cNd    =   new NodeUtil();
                                rNd.Nodes.Add(cNd);

                                labels              =   cellNode.SelectNodes("labels/label");
                                found               =   false;
                                sb                  =   new StringBuilder();
                                foreach (XmlNode labNode in labels)
                                {
                                    if ((labels.Count == 1) || (labNode.Attributes["languagecode"].InnerText == LCID))
                                    {
                                        sb1.AppendFormat("{0} '{1}'", labNode.Attributes["description"].InnerText);
                                        found   =   true;
                                        break;
                                    }
                                }
                                 */
                                XmlNodeList controls = cellNode.SelectNodes("control");
                                foreach (XmlNode controlNode in controls)
                                {
                                    string clsid        =   controlNode.Attributes["classid"].InnerText;
                                    StringBuilder sb2   =   new StringBuilder();
                                    sb2.AppendFormat("{0} ", controlNode.Attributes["id"].InnerText);
                                    if ( controlNode.Attributes["datafieldname"] != null )
                                        sb2.AppendFormat("DataFieldName: {0} ", controlNode.Attributes["datafieldname"].InnerText);
                                    if ( controlNode.Attributes["disabled"] != null )
                                        sb1.AppendFormat(", disabled: {0} ",controlNode.Attributes["disabled"].InnerText);
                                    switch (clsid)
                                    {
                                        case clsIdCheckBox:
                                            sb2.Append("CheckBox");
                                            break;
                                        case clsIdDateTime:
                                            sb2.Append("DateTime");
                                            break;
                                        case clsIdDecimal:
                                            sb2.Append("Decimal");
                                            break;
                                        case clsIdDuration:
                                            sb2.Append("Duration");
                                            break;
                                        case clsIdEmailAddress:
                                            sb2.Append("EmailAddress");
                                            break;
                                        case clsIdEmailBody:
                                            sb2.Append("EmailBody");
                                            break;
                                        case clsIdFloat:
                                            sb2.Append("Float");
                                            break;
                                        case clsIdIFrame:
                                            sb2.Append("IFrame");
                                            break;
                                        case clsIdInteger:
                                            sb2.Append("Integer");
                                            break;
                                        case clsIdLanguage:
                                            sb2.Append("Language");
                                            break;
                                        case clsIdLookup:
                                            sb2.Append("Lookup");
                                            break;
                                        case clsIdMoney:
                                            sb2.Append("Money");
                                            break;
                                        case clsIdNotes:
                                            sb2.Append("Notes");
                                            break;
                                        case clsIdPartyListLookup:
                                            sb2.Append("PartyListLookup");
                                            break;
                                        case clsIdPicklist:
                                            sb2.Append("Picklist");
                                            break;
                                        case clsIdRadiobuttons:
                                            sb2.Append("Radiobuttons");
                                            break;
                                        case clsIdRegardingLookup:
                                            sb2.Append("RegardingLookup");
                                            break;
                                        case clsIdStatusReason:
                                            sb2.Append("StatusReason");
                                            break;
                                        case clsIdTextArea:
                                            sb2.Append("TextArea");
                                            break;
                                        case clsIdTextBox:
                                            sb2.Append("TextBox");
                                            break;
                                        case clsIdTickerSymbol:
                                            sb2.Append("TickerSymbol");
                                            break;
                                        case clsIdTimeZonePicklist:
                                            sb2.Append("TimeZonePicklist");
                                            break;
                                        case clsIdUrl:
                                            sb2.Append("Url");
                                            break;
                                        default:
                                            sb2.Append("UNKNOWN");
                                            break;
                                    }
                                    nd              =   new NodeUtil(sb2.ToString(),NodeType.Control);
                                    nd.Id           =   controlNode.Attributes["id"].InnerText;
                                    rNd.Nodes.Add(nd);
                                    XmlNodeList parameters = controlNode.SelectNodes("parameters");
                                    foreach (XmlNode paramNode in parameters)
                                    {
                                        XmlNode snd = paramNode.SelectSingleNode("Url");
                                        if (snd != null)
                                            nd.Nodes.Add(new NodeUtil(string.Format("Url={0}",snd.InnerText),NodeType.Parameter));
                                        snd = paramNode.SelectSingleNode("PassParameters");
                                        if (snd != null)
                                            nd.Nodes.Add(new NodeUtil(string.Format("PassParameters={0}",snd.InnerText),NodeType.Parameter));
                                        snd = paramNode.SelectSingleNode("Security");
                                        if (snd != null)
                                            nd.Nodes.Add(new NodeUtil(string.Format("security={0}",snd.InnerText),NodeType.Parameter));
                                        snd = paramNode.SelectSingleNode("Scrolling");
                                        if (snd != null)
                                            nd.Nodes.Add(new NodeUtil(string.Format("Scrolling={0}",snd.InnerText),NodeType.Parameter));
                                        snd = paramNode.SelectSingleNode("Border");
                                        if (snd != null)
                                            nd.Nodes.Add(new NodeUtil(string.Format("Border={0}",snd.InnerText),NodeType.Parameter));
                                        snd = paramNode.SelectSingleNode("AutoResolve");
                                        if (snd != null)
                                            nd.Nodes.Add(new NodeUtil(string.Format("AutoResolve={0}",snd.InnerText),NodeType.Parameter));
                                    }
                                }
                                XmlNodeList events = cellNode.SelectNodes("events/event");
                                foreach (XmlNode eventNode in events)
                                {
                                    StringBuilder sb2   =   new StringBuilder();
                                    sb2.AppendFormat("{0} ", eventNode.Attributes["name"].InnerText);
                                    if ( eventNode.Attributes["active"] != null )
                                        sb2.AppendFormat("active: {0} ", eventNode.Attributes["active"].InnerText);
                                    nd              =   new NodeUtil(sb2.ToString(),NodeType.Event);
                                    rNd.Nodes.Add(nd);
                                    XmlNode script =   eventNode.SelectSingleNode("script");
                                    if ( script != null )
                                    {
                                        nd.Nodes.Add(new NodeUtil(script.InnerText,NodeType.Script));
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return RadTreeView1;
        }
        #endregion Build a tree with Crm frame data

        #region public methods

        public string RetrieveForm()
        {
            RetrieveFormXml req     =   new RetrieveFormXml(entityName);
            req.Run(wrapper);
            return req.formXml;
        }

        /// <summary>
        /// Export Crm Form data into DataXml property of this object
        /// </summary>
        public string ExportXml()
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form ExportXml BEG EntName: {0}", entityName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            ImportExportXml ImportExportData    =   new ImportExportXml(entityName);
            bool ret                            =   ImportExportData.Export(wrapper);
            if ( ret)
            {
                DataXml                         =   ImportExportData.DataXml;
            }
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form ExportXml END ret: {0}", ret),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return DataXml;
        }

        /// <summary>
        /// Import Crm Form data from DataXml property of this object
        /// </summary>
        public string ImportXml(bool publish)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form ImportXml BEG EntName: {0}, publish: {1}", entityName,publish),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            if ( string.IsNullOrEmpty(DataXml) )
            {
                    DataXml                     =   _metadata.InnerXml;
            }
            ImportExportXml ImportExportData    =   new ImportExportXml(entityName,DataXml);
            bool ret                            =   ImportExportData.Import(wrapper,publish);
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form ImportXml END ret: {0}", ret),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return DataXml;
        }

        public bool AddNewIframe(string url,bool publish)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddNewIframe BEG EntName: {0}, url: {1}", entityName, url),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            bool ret            =   AddIframe(true,true,iFrameTabName, iFrameSectionName, rowSpan, colSpan, iFrameName,url,publish);
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddNewIframe END ret: {0}", ret),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return ret;
        }
        
        /// <summary>
        /// Add an Iframe in an existing Tab
        /// </summary>
        public bool AddNewIframe(string tabId,string url,bool publish)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddNewIframe in existing tab BEG EntName: {0}, tabId: {1}, url: {2}", entityName,tabId, url),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            bool ret            =   AddIframe(false,true,tabId, iFrameSectionName, rowSpan, colSpan, iFrameName,url,publish);
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddNewIframe END ret: {0}", ret),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return ret;
        }

        public bool AddNewIframe(string tabName,string sectionName,string url,bool publish)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddNewIframe BEG EntName: {0}, url: {1}", entityName, url),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            bool ret            =   AddIframe(false,false,tabName, sectionName, rowSpan, colSpan, iFrameName,url,publish);
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddNewIframe END ret: {0}", ret),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return ret;
        }

        /// <summary>
        /// One shoot operation: Export from Crm / AddIframe / Import / eventually publish
        /// When adding in existing Tab and/or section, tabName and sectionName must be the ids of existing tabs and sections
        /// </summary>
        public bool AddIframe(bool newTab,bool newSection,string tabName, string sectionName, int wrowspan, int wcolspan, string iFrameName, string url,bool publish)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddIframe BEG newTab: {0},newSection: {1},EntName: {2}, tabName: {3}, sectionName: {4}, rowspan: {5}, colspan: {6}, iFrameName: {7}, url: {8}, publish: {9}", 
                    new object[]{newTab,newSection,entityName,tabName,sectionName,wrowspan,wcolspan,iFrameName,url,publish}),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            _iFrameTabName                          =   tabName;
            _iFrameSectionName                      =   sectionName;
            _iFrameName                             =   iFrameName;
            rowSpan                                 =   wrowspan;
            colSpan                                 =   wcolspan;

            bool ret                                =   false;
            try
            {
                ImportExportXml ImportExportData    =   new ImportExportXml(entityName);
                ret                                 =   ImportExportData.Export(wrapper);
                if ( ret )
                {
                    DataXml                         =   ImportExportData.DataXml;
                    LoadMetaData();
                    if (!newTab)
                    {
                        if (!newSection)
                                ret                 =   AddIframeInExistingTabAndSection(url);
                        else    ret                 =   AddIframeInExistingTabNewSection(url);
                    }
                    else ret                        =   AddIframeInNewTab(url);
                }
                if (ret)
                {
                    DataXml                         =   _metadata.InnerXml;
                    ImportExportData.DataXml        =   DataXml;
                    ret                             =   ImportExportData.Import(wrapper,publish);
                }
            }
			catch (Exception ex)
			{
                if ( CRMMetaTrace.Sw.TraceError || InstallTraceSwitchW.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CrmUtil4Form AddIframe ex: {0}",ex),(CRMMetaTrace.Sw.TraceError) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
			}
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddIframe END ret: {0}", ret),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return ret;
        }
 
        /// <summary>
        /// Do the Export from Crm only, DataXml propety contains the exported datas
        /// </summary>
        public ImportExportXml Init()
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form Init BEG EntName: {0}",entityName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            ImportExportXml ImportExportData        =   new ImportExportXml(entityName);
            try
            {
                if (  ImportExportData.Export(wrapper) )
                {
                    DataXml                         =   ImportExportData.DataXml;
                    if ( CRMMetaTrace.Sw.TraceVerbose )
                        Trace.WriteLine(string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form Init DataXml: '{0}'.",DataXml),CRMMetaTrace.Sw.Info);
                    LoadMetaData();
               }
            }
			catch (Exception ex)
			{
                if ( CRMMetaTrace.Sw.TraceError || InstallTraceSwitchW.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CrmUtil4Form AddIframe ex: {0}",ex),(CRMMetaTrace.Sw.TraceError) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
			}
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine("[V]CrmUtil4Form Init END.",(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return ImportExportData;
        }
         
        /// <summary>
        /// Add the Iframe without importing modified datas contained into DataXml to Crm
        /// </summary>
        public bool AddNewIframeNoImport(string url)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddNewIframeNoImport BEG EntName: {0}, url: {1}", entityName, url),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            bool ret            =   AddIframeNoImport(true,true,iFrameTabName, iFrameSectionName, rowSpan, colSpan, iFrameName,url);
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddNewIframeNoImport END ret: {0}", ret),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return ret;
        }

        public bool AddNewIframeNoImport(string tabName,string url)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddNewIframeNoImport BEG EntName: {0}, url: {1}", entityName, url),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            bool ret            =   AddIframeNoImport(false,true,tabName, iFrameSectionName, rowSpan, colSpan, iFrameName,url);
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddNewIframeNoImport END ret: {0}", ret),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return ret;
        }

        /// <summary>
        /// Beware: it uses parameters of this class: tabName, sectionName, rowSpan, colSpan, iFrameName
        /// Must be set before or get default values
        /// </summary>
        public bool AddNewIframeNoImport(string tabName,string sectionName,string url)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddNewIframeNoImport BEG EntName: {0}, url: {1}", entityName, url),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            bool ret            =   AddIframeNoImport(false,false,tabName, sectionName, rowSpan, colSpan, iFrameName,url);
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddNewIframeNoImport END ret: {0}", ret),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return ret;
        }

        public bool AddNewIframeNoImport(XmlElement section,string url, int wrowspan, int wcolspan)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddNewIframeNoImport BEG EntName: {0}, url: {1}", entityName, url),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            if ( wrowspan != 0 )
                rowSpan                         =   wrowspan;
            if ( wcolspan != 0 )
                colSpan                         =   wcolspan;

            bool ret                            =   false;
            try
            {
                    ret                         =   AddIframeInExistingXmlSection(section,url);
            }
			catch (Exception ex)
			{
                if ( CRMMetaTrace.Sw.TraceError || InstallTraceSwitchW.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CrmUtil4Form AddIframeNoImport ex: {0}",ex),(CRMMetaTrace.Sw.TraceError) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
			}
       
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddNewIframeNoImport END ret: {0}", ret),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return ret;
        }

        /// <summary>
        /// When adding in existing Tab and/or section, tabName and sectionName must be the ids of existing tabs and sections
        /// </summary>
        public bool AddIframeNoImport(bool newTab,bool newSection,string tabName, string sectionName, int wrowspan, int wcolspan, string iFrameName, string url)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddIframeNoImport BEG newTab: {0},newSection: {1},EntName: {2}, tabName: {3}, sectionName: {4}, rowspan: {5}, colspan: {6}, iFrameName: {7}, url: {8}", 
                    new object[]{newTab,newSection,entityName,tabName,sectionName,wrowspan,wcolspan,iFrameName,url}),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            _iFrameTabName                      =   tabName;
            _iFrameSectionName                  =   sectionName;
            _iFrameName                         =   iFrameName;
            rowSpan                             =   wrowspan;
            colSpan                             =   wcolspan;

            bool ret                            =   false;
            try
            {
                if (!newTab)
                {
                    if (!newSection)
                            ret                 =   AddIframeInExistingTabAndSection(url);
                    else    ret                 =   AddIframeInExistingTabNewSection(url);
                }
                else ret                        =   AddIframeInNewTab(url);
            }
			catch (Exception ex)
			{
                if ( CRMMetaTrace.Sw.TraceError || InstallTraceSwitchW.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CrmUtil4Form AddIframeNoImport ex: {0}",ex),(CRMMetaTrace.Sw.TraceError) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
			}
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form AddIframeNoImport END ret: {0}", ret),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return ret;
        }
        
        /// <summary>
        /// After a serie of updates stored in DataXml property, import them to Crm and eventually publish
        /// </summary>
        public bool Save(ImportExportXml ImportExportData,bool publish)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form Save BEG EntName: {0}, publish: {1}",entityName,publish),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            if ( ImportExportData == null)
                ImportExportData                    =   new ImportExportXml(entityName);
            bool ret                                =   false;
            try
            {
                    DataXml                         =   _metadata.InnerXml;
                    ImportExportData.DataXml        =   DataXml;
                    ret                             =   ImportExportData.Import(wrapper,publish);
            }
			catch (Exception ex)
			{
                if ( CRMMetaTrace.Sw.TraceError || InstallTraceSwitchW.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CrmUtil4Form Save ex: {0}",ex),(CRMMetaTrace.Sw.TraceError) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
			}
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CrmUtil4Form Save END ret: {0}", ret),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return ret;
        }
        
        #endregion public methods
    }
}